package com.xuecheng.manage_course.service;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.response.CmsPageResult;
import com.xuecheng.framework.domain.cms.response.CmsPostPageResult;
import com.xuecheng.framework.domain.course.*;
import com.xuecheng.framework.domain.course.ext.CourseInfo;
import com.xuecheng.framework.domain.course.ext.CourseView;
import com.xuecheng.framework.domain.course.ext.TeachplanNode;
import com.xuecheng.framework.domain.course.request.CourseListRequest;
import com.xuecheng.framework.domain.course.response.CourseCode;
import com.xuecheng.framework.domain.course.response.CoursePublishResult;
import com.xuecheng.framework.domain.course.response.TeachplanMediaPub;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.manage_course.client.CmsPageClient;
import com.xuecheng.manage_course.dao.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
public class CourseService {
    //课程计划查询
    @Autowired
    private CourseBaseRepository courseBaseRepository;
    @Autowired
    private TeachplanMapper teachplanMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private TeachplanRepository teachplanRepository;

    //课程图片
    @Autowired
    private CoursePicRepositor coursePicRepositor;

    //课程销售
    @Autowired
    private CourseMarkerRespository courseMarkerRespository;

    //Day_14 17: 课程与媒资的结合
    @Autowired
    private TeachplanMediaRepository teachplanMediaRepository;

    //Day_15@6: 根据课程id删除 teachplan_media_pub
    private TeachplanMediaPubRepository teachplanMediaPubRepository;


    //课程信息汇总 course_pub
    private CoursePubRepository coursePubRepository;

    @Value("${course-publish.dataUrlPre}")
    private String publish_dataUrlPre;
    @Value("${course-publish.pagePhysicalPath}")
    private String publish_page_physicalpath;
    @Value("${course-publish.pageWebPath}")
    private String publish_page_webpath;
    @Value("${course-publish.siteId}")
    private String publish_siteId;
    @Value("${course-publish.templateId}")
    private String publish_templateId;
    @Value("${course-publish.previewUrl}")
    private String previewUrl;
    //注入远程服务  cms
    private CmsPageClient cmsPageClient;

    public TeachplanNode findTeachplanList(String courseId) {
        return teachplanMapper.selectList(courseId);
    }

    @Transactional
    public ResponseResult addTeachplan(Teachplan teachplan) {
        if (teachplan == null || StringUtils.isEmpty(teachplan.getCourseid()) || StringUtils.isEmpty(teachplan.getPname())) {
            ExceptionCast.cast(CommonCode.INVALID_PARAM);
        }
        String courseId = teachplan.getCourseid();
        String parentId = teachplan.getParentid();
        //如果parentid为空,则将这个课程设置为  根节点
        //再取出其根节点
        if (StringUtils.isEmpty(parentId)) {
            parentId = this.getTeachplanRoot(courseId);
        }
        //----根节点 为新创建的一级 -----
        //接下来  创建一个新的子结点
        Teachplan teachplanNew = new Teachplan();
        //将页面填写的信息,拷贝到teachplanNew中
        Optional<Teachplan> optional = teachplanRepository.findById(parentId);
        Teachplan teachplan1 = optional.get();
        String parentGrade = teachplan1.getGrade();

        BeanUtils.copyProperties(teachplan, teachplanNew);
        teachplanNew.setParentid(parentId);
        teachplanNew.setCourseid(courseId);
        //根据父结点的grade决定子结点的grade
        if (parentGrade.equals("1")) {
            teachplanNew.setGrade("2");
        } else {
            teachplanNew.setGrade("3");
        }
        teachplanRepository.save(teachplanNew);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //查询添加的该课程是否有根节点
    private String getTeachplanRoot(String courseId) {
        Optional<CourseBase> optional = courseBaseRepository.findById(courseId);
        if (!optional.isPresent()) {
            return null;
        }


        CourseBase courseBase = optional.get();
        List<Teachplan> teachplans = teachplanRepository.findByCourseidAndParentid(courseId, "0");
        if (teachplans == null || teachplans.size() <= 0) {
            //查询不到时,将传过来的课程设置为根节点
            Teachplan teachplan = new Teachplan();
            teachplan.setParentid("0");
            teachplan.setGrade("1");
            teachplan.setPname(courseBase.getName());
            teachplan.setCourseid(courseId);
            teachplan.setStatus("0");
        }
        return teachplans.get(0).getId();
    }

    public QueryResponseResult<CourseInfo> findCourseList(String companyId,int currentPage, int pageSize, CourseListRequest courseListRequest) {
        //Day_18@15: 加细粒度授权   我没有加,如果要加需要动Dao
        PageHelper.startPage(currentPage, pageSize);
        Page<CourseInfo> courseListPage = courseMapper.findCourseListPage(courseListRequest);

        List<CourseInfo> result = courseListPage.getResult();
        Long total = courseMapper.findCount();
        QueryResult queryResult = new QueryResult(result, total);
        return new QueryResponseResult<>(CommonCode.SUCCESS, queryResult);
    }

    @Transactional
    /**
     * 添加课程图片
     * @param courseId  课程分类的模块标识符
     * @param pic   图片在mongodb的filesystem中的id
     * @return 基本返回:三件套  是否成功 操作代码  提示信息
     */
    public ResponseResult saveCoursePic(String courseId, String pic) {
        //查询课程图片
        Optional<CoursePic> picOptional = coursePicRepositor.findById(courseId);
        CoursePic coursePic = null;
        if (picOptional.isPresent()) {
            coursePic = picOptional.get();
        }
        //没有课程图片则创建对象
        if (coursePic == null) {
            coursePic = new CoursePic();
        }
        coursePic.setCourseid(courseId);
        coursePic.setPic(pic);
        //保存课程图片
        coursePicRepositor.save(coursePic);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
     * 获取课程基础信息
     *
     * @param courseid 课程分类的模块标识符
     * @return Course类, 图片id+分类id
     */
    public CoursePic findCoursePic(String courseid) {
        CoursePic coursePic1 = null;
        Optional<CoursePic> coursePic = coursePicRepositor.findById(courseid);
        if (coursePic.isPresent()) {
            coursePic1 = coursePic.get();
        }
        return coursePic1;
    }

    /**
     * 删除课程图片
     *
     * @param courseId 课程分类的模块标识符
     * @return 基本返回:三件套  是否成功 操作代码  提示信息
     * <p>
     * 因为:每个课程的图片只有一个,使用如果删除失败那就是数据库没有图片.代码执行异常 返回操作失败
     */
    @Transactional
    public ResponseResult deleteCoursePic(String courseId) {
        try {
            coursePicRepositor.deleteById(courseId);
        } catch (Exception e) {
            return new ResponseResult(CommonCode.FAIL);
        }
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //查询课程视图,包括基本信息,图片,营销,课程计划
    public CourseView getCoruseView(String id) {
        //定义返回视图对象
        CourseView courseView = new CourseView();

        //1.查询课程基本信息
        Optional<CourseBase> optional = courseBaseRepository.findById(id);
        if (optional.isPresent()) {
            CourseBase courseBase = optional.get();
            //封装对象
            courseView.setCourseBase(courseBase);
        }
        //2.查询课程销售信息
        Optional<CourseMarket> byId = courseMarkerRespository.findById(id);
        if (byId.isPresent()) {
            CourseMarket courseMarket = byId.get();
            //封装对象
            courseView.setCourseMarket(courseMarket);
        }
        //3.查询课程图片
        Optional<CoursePic> coursePic = coursePicRepositor.findById(id);
        if (coursePic.isPresent()) {
            CoursePic coursePic1 = coursePic.get();
            //封装对象
            courseView.setCoursePic(coursePic1);
        }
        //4.查询课程计划信息
        TeachplanNode teachplanNode = teachplanMapper.selectList(id);
        courseView.setTeachplanNode(teachplanNode);
        return courseView;
    }

    //day_09----------------------------------------------------------------------------------
    //根据id查询课程基本信息
    public CourseBase findCourseBaseById(String courseId) {
        Optional<CourseBase> baseOptional = courseBaseRepository.findById(courseId);
        if (baseOptional.isPresent()) {
            CourseBase courseBase = baseOptional.get();
            return courseBase;
        }
        ExceptionCast.cast(CourseCode.COURSE_GET_NOTEXISTS);
        return null;
    }

    /**
     * 课程预览
     *
     * @param courseId sql中页面id
     * @return mongodb  拼接页面预览的url
     */

    public CoursePublishResult preview(String courseId) {
        CourseBase one = this.findCourseBaseById(courseId);
        //1.请求cms添加页面
        //准备cmsPage信息
        CmsPage cmsPage = new CmsPage();

        //站点
        cmsPage.setSiteId(publish_siteId);//课程预览站点
        //模板
        cmsPage.setTemplateId(publish_templateId);
        //页面名称
        cmsPage.setPageName(courseId + ".html");
        //页面别名
        cmsPage.setPageAliase(one.getName());
        //页面访问路径
        cmsPage.setPageWebPath(publish_page_webpath);
        //页面存储路径
        cmsPage.setPagePhysicalPath(publish_page_physicalpath);
        //数据url
        cmsPage.setDataUrl(publish_dataUrlPre + courseId);

        //远程调用Cms  --存储页面 拿到存储id
        CmsPageResult cmsPageResult = cmsPageClient.save(cmsPage);
        if (!cmsPageResult.isSuccess()) {
            //返回失败信息
            return new CoursePublishResult(CommonCode.FAIL, null);
        }
        //从返回结果中拿到对象
        CmsPage cmsPage1 = cmsPageResult.getCmsPage();
        //从对象中拿到存储后的id
        String pageId = cmsPage1.getPageId();


        //2.拼接页面预览的url
        String Url = previewUrl + pageId;
        //3.返回CoursePublishResult
        return new CoursePublishResult(CommonCode.SUCCESS, Url);
    }

    //课程发布
    @Transactional
    public CoursePublishResult publish(String courseId) {
        //1.调用cms一键发布接口将课程详情页面发布到服务器
        CourseBase one = this.findCourseBaseById(courseId);
        //准备cmsPage信息
        CmsPage cmsPage = new CmsPage();

        //站点
        cmsPage.setSiteId(publish_siteId);//课程预览站点
        //模板
        cmsPage.setTemplateId(publish_templateId);
        //页面名称
        cmsPage.setPageName(courseId + ".html");
        //页面别名
        cmsPage.setPageAliase(one.getName());
        //页面访问路径
        cmsPage.setPageWebPath(publish_page_webpath);
        //页面存储路径
        cmsPage.setPagePhysicalPath(publish_page_physicalpath);
        //数据url
        cmsPage.setDataUrl(publish_dataUrlPre + courseId);
        //调用cms一键发布接口将课程详情页面发布到服务器
        CmsPostPageResult cmsPostPageResult = cmsPageClient.postPageQuick(cmsPage);
        if (!cmsPostPageResult.isSuccess()) {
            ExceptionCast.cast(CommonCode.FAIL);
        }
        //2.保存课程的发布状态为"已发布"
        //保存课程的发布状态为“已发布”
        CourseBase courseBase = this.saveCoursePubState(courseId);
        if (courseBase == null) {
            return new CoursePublishResult(CommonCode.FAIL, null);
        }
        //3.保存课程索引信息
        //3-1先创建一个coursePub对象
        CoursePub coursePub = createCoursePub(courseId);
        //3-2将coursePub对象保存到数据库
        saveCoursePub(courseId,coursePub);
        //4.缓存课程信息
        //得到页面的url
        String pageUrl = cmsPostPageResult.getPageUrl();


        //Day_15@6:保存课程计划媒资信息   --主要是多个时间戳 方便采取
       //向teachplanMediaPub中保存课程媒资信息
        saveTeachplanMediaPub(courseId);

        return new CoursePublishResult(CommonCode.SUCCESS, pageUrl);
    }

    //Day_15@6:向teachplanMediaPub中保存课程媒资信息
    private void saveTeachplanMediaPub(String courseId){
        //第一件事:先删除teachplanMediaPub中的数据
        teachplanMediaPubRepository.deleteByCourseId(courseId);
        //第二件事:插入最新信息到teachplanMediaPub表中    ---它有时间戳
        //2-1:从teachplanMedia中查询   --原始数据
        List<TeachplanMedia> teachplanMediaList = teachplanMediaRepository.findByCourseId(courseId);
        //2-2:将teachplanMediaList数据放到       ---teachplanMediaPubs中
        List<TeachplanMediaPub> teachplanMediaPubs = new ArrayList<>();
        for(TeachplanMedia teachplanMedia:teachplanMediaList){

            TeachplanMediaPub teachplanMediaPub = new TeachplanMediaPub();
            //                       复制                 被复制
            BeanUtils.copyProperties(teachplanMedia,teachplanMediaPub);
            //添加时间戳
            teachplanMediaPub.setTimestamp(new Date());
            teachplanMediaPubs.add(teachplanMediaPub);
        }

        //将teachplanMediaList插入到teachplanMediaPub
        teachplanMediaPubRepository.saveAll(teachplanMediaPubs);
    }

    //3-2将coursePub对象保存到数据库
    private CoursePub  saveCoursePub(String id,CoursePub coursePub){
        CoursePub coursePubNew = null;
        //根据课程i的查询course_pub
        Optional<CoursePub> coursePub1 = coursePubRepository.findById(id);
        if (coursePub1.isPresent()){
            coursePubNew = coursePub1.get();
        }else {
            coursePubNew=  new CoursePub();
        }
        //将coursePub对象中的信息保存到coursePubNew中
        BeanUtils.copyProperties(coursePub,coursePubNew);
        //保证拷贝和复制的id统一
        coursePubNew.setId(id);
        //时间戳,给logstach使用
        coursePubNew.setTimestamp(new Date());
        //发布时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(new Date());
        coursePubNew.setPubTime(format);
        //存储数据
        coursePubRepository.save(coursePubNew);
        return coursePubNew;
    }

    //3-1先创建一个coursePub对象
    private CoursePub createCoursePub(String id){
        CoursePub coursePub = new CoursePub();
        //根据课程id查询course_base
        Optional<CourseBase> base = courseBaseRepository.findById(id);
        if (base.isPresent()){
            CourseBase courseBase = base.get();
            //将CourseBase属性拷贝到CoursePub中
            BeanUtils.copyProperties(courseBase,coursePub);
        }

        //查询课程图片
        Optional<CoursePic> picOptional = coursePicRepositor.findById(id);
        if(picOptional.isPresent()){
            CoursePic coursePic = picOptional.get();
            BeanUtils.copyProperties(coursePic, coursePub);
        }

        //课程营销信息
        Optional<CourseMarket> marketOptional = courseMarkerRespository.findById(id);
        if(marketOptional.isPresent()){
            CourseMarket courseMarket = marketOptional.get();
            BeanUtils.copyProperties(courseMarket, coursePub);
        }

        //课程计划信息
        TeachplanNode teachplanNode = teachplanMapper.selectList(id);
        String jsonString = JSON.toJSONString(teachplanNode);
        //将课程计划信息json串保存到 course_pub中
        coursePub.setTeachplan(jsonString);
        return coursePub;
    }

    //更新课程状态为已发布 202002
    private CourseBase saveCoursePubState(String courseId) {
        CourseBase courseBaseById = this.findCourseBaseById(courseId);
        courseBaseById.setStatus("202002");
        courseBaseRepository.save(courseBaseById);
        return courseBaseById;
    }

    /**
     * Day14:课程计划与视频产生关系   video:17
     * @param teachplanMedia   课程成id    视频id
     * @return
     */
    public ResponseResult savemedia(TeachplanMedia teachplanMedia) {
        //第一件事:判断传入对象是非为空
        if (teachplanMedia == null){
            //如果前台页面传参为空,报非法参数
            ExceptionCast.cast(CommonCode.INVALID_PARAM);
        }

        //第二件事:不是3级课程不允许添加视频   查询小海豚 teachplan
        //2-1:获取课程计划
        String teachplanId = teachplanMedia.getTeachplanId();
        //2-2:查询课程计划
        //2-2-1:查询该ID的课程信息存在不存在
        Optional<Teachplan> optional = teachplanRepository.findById(teachplanId);
        if (!optional.isPresent()){
            ExceptionCast.cast(CourseCode.COURSE_MEDIA_TEACHPLAN_ISNULL);
        }
        //查询到教学计划
        Teachplan teachplan = optional.get();
        //2-2-2:只允许三级结点课程计划选择视频
        String grade = teachplan.getGrade();
        if (StringUtils.isEmpty(grade)|| !grade.equals("3")){
            ExceptionCast.cast(CourseCode.COURSE_MEDIA_TEACHPLAN_GRADEERROR);
        }
        //第三件事:保存媒资信息与课程计划信息
        //3-1:查询该课程ID在teachplan_media表中的数据    小海豚 teachplan_media
        Optional<TeachplanMedia> teachplanMediaOptional = teachplanMediaRepository.findById(teachplanId);
        TeachplanMedia one =  null;
        if (!teachplanMediaOptional.isPresent()){
            one = new  TeachplanMedia();
        }else {
            one = teachplanMediaOptional.get();
        }
        //3-2:保存媒资信息与课程计划信息
        //将one保存到数据库
        one.setCourseId(teachplan.getCourseid());//课程id
        one.setMediaId(teachplanMedia.getMediaId());//媒资文件的id    *(页面传递)
        one.setMediaFileOriginalName(teachplanMedia.getMediaFileOriginalName());//媒资文件的原始名称
        one.setMediaUrl(teachplanMedia.getMediaUrl());//媒资文件的url
        one.setTeachplanId(teachplanId);
        teachplanMediaRepository.save(one);

        return new ResponseResult(CommonCode.SUCCESS);
    }
}